import os
import sys
import subprocess
import random
import re
import requests
import uuid
import json
import time
from pathlib import Path
from http import HTTPStatus
from dashscope import Generation
import dashscope
from dotenv import load_dotenv
import pandas as pd

# 加载.env文件中的环境变量
load_dotenv()

# 设置API密钥和基础URL
api_key = os.getenv("DASHSCOPE_API_KEY")
if api_key:
    dashscope.api_key = api_key
    dashscope.base_http_api_url = 'https://dashscope.aliyuncs.com/api/v1'

# 检查API密钥是否存在
if not api_key:
    raise ValueError("未找到DASHSCOPE_API_KEY环境变量，请检查.env文件配置")

# 全局变量用于存储任务引用
current_task_ref = None


def set_current_task(task_ref):
    """
    设置当前任务引用，用于实时更新日志
    """
    global current_task_ref
    current_task_ref = task_ref


def update_task_log(log_message):
    """
    实时更新任务日志
    """
    global current_task_ref
    if current_task_ref and 'log' in current_task_ref:
        # 添加新日志行
        if current_task_ref['log']:
            current_task_ref['log'] += '\n' + log_message
        else:
            current_task_ref['log'] = log_message


def generate_humor_script(team_a, team_b, match_time, match_name):
    """
    根据球队信息和比赛时间生成幽默剧情文本（越南语版本）
    
    Args:
        team_a (str): 球队A名称
        team_b (str): 球队B名称
        match_time (str): 比赛时间
        match_name (str): 赛事名称
        
    Returns:
        tuple: (成功状态, 结果信息)
    """
    try:
        # 构造提示词（越南语）
        prompt = f"""请为以下足球比赛生成一段10秒的幽默剧情文本，用于视频生成。要求如下：
1. 球队A: {team_a}
2. 球队B: {team_b}
3. 比赛时间: {match_time}
4. 赛事名称: {match_name}
5. 要求：
   - 内容使用越南语
   - 风格幽默但真实，避免低俗内容
   - 包含足球元素，背景要有足球相关描写
   - 可以包含球迷采访、评论等场景
   - 如果出现非越南人角色，需要体现其口音特点
   - 使用越南网络流行语，如："xịt", "cay", "gà", "mạnh ai nấy lấy", "bốc phét"等
   - 以对话形式展现，包含2-3个角色
   - 为视频生成提供详细描述，包括：
     * 角色外观特征（服装、表情、动作）
     * 场景细节（足球场、观众席、球门等）
     * 光线和色彩氛围
     * 角色的具体动作和表情变化
     * 镜头运动方式（推拉摇移等）
   - 确保内容能在10秒内演绎完成

请直接输出剧情内容，不要包含其他说明文字。"""

        messages = [
            {"role": "system", "content": "你是一个专业的视频编剧，擅长创作包含足球元素的幽默短剧，能够用越南语进行创作。"},
            {"role": "user", "content": prompt}
        ]
        
        update_task_log(f"正在生成幽默剧情文本...")
        update_task_log(f"球队A: {team_a}")
        update_task_log(f"球队B: {team_b}")
        update_task_log(f"比赛时间: {match_time}")
        update_task_log(f"赛事名称: {match_name}")
        
        response = Generation.call(
            model="qwen-plus",
            messages=messages,
            result_format="message",
        )

        if response.status_code == 200:
            script = response.output.choices[0].message.content
            update_task_log(f"剧情文本生成成功: {script}")
            return True, script
        else:
            error_msg = f"生成失败，状态码: {response.status_code}, 错误信息: {response.message}"
            update_task_log(error_msg)
            return False, error_msg
            
    except Exception as e:
        error_msg = f"生成剧情文本时出错: {str(e)}"
        update_task_log(error_msg)
        return False, error_msg


def generate_video_from_text(script_text, output_path, duration=10, resolution="480*832"):
    """
    根据文本生成视频
    
    Args:
        script_text (str): 剧情文本
        output_path (str): 输出视频路径
        duration (int): 视频时长(秒)
        resolution (str): 视频分辨率，默认为"480*832"
        
    Returns:
        tuple: (成功状态, 结果信息)
    """
    try:
        update_task_log(f"正在生成视频...")
        update_task_log(f"剧情内容: {script_text}")
        update_task_log(f"目标时长: {duration}秒")
        update_task_log(f"视频分辨率: {resolution}")
        
        # 构造简洁的视频生成提示词，强调写实风格和足球元素，控制在500字以内
        video_prompt = f"""{script_text}
        
视频生成要求：
1. 写实风格，真人演员，场景逼真
2. 包含足球元素（球场、观众席、球门、足球等）
3. 人物对话使用越南语，非越南人需体现口音
4. 保持对话内容不变
5. 视频时长{duration}秒，分辨率{resolution}
6. 增强真实感细节：
   - 角色外观（服装、发型、面部特征等）
   - 环境细节（草坪纹理、观众席、广告牌等）
   - 自然光照和阴影效果
   - 角色动作自然流畅
   - 摄像机运动效果（推拉摇移等）"""

        # 使用与文本生成视频.py相同的API调用方式
        headers = {
            'X-DashScope-Async': 'enable',
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }
        
        data = {
            "model": "wan2.5-t2v-preview",
            "input": {
                "prompt": video_prompt
            },
            "parameters": {
                "size": resolution,
                "prompt_extend": True,
                "watermark": False,
                "duration": duration,
                "audio": True
            }
        }
        
        update_task_log("正在提交视频生成任务...")
        response = requests.post(
            'https://dashscope.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis',
            headers=headers,
            json=data
        )
        
        if response.status_code == 200:
            response_data = response.json()
            print(f"视频生成API完整响应: {response_data}")
            
            # 检查响应中是否包含任务ID
            if 'output' not in response_data or 'task_id' not in response_data['output']:
                error_msg = f"视频生成任务提交成功，但响应中未包含task_id字段。完整响应: {response_data}"
                update_task_log(error_msg)
                return False, error_msg
                
            task_id = response_data['output']['task_id']
            update_task_log(f"视频生成任务已提交，任务ID: {task_id}")
            
            # 等待任务完成
            video_url = None
            task_status = None
            max_attempts = 60  # 最多等待10分钟(60次*10秒)
            attempt = 0
            
            while attempt < max_attempts:
                update_task_log(f"正在等待视频生成完成... (尝试 {attempt+1}/{max_attempts})")
                time.sleep(10)  # 等待10秒后查询状态
                
                # 查询任务状态
                status_response = requests.get(
                    f'https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}',
                    headers={'Authorization': f'Bearer {api_key}'}
                )
                
                print(f"任务状态查询响应状态码: {status_response.status_code}")
                
                if status_response.status_code == 200:
                    status_data = status_response.json()
                    print(f"任务状态查询完整响应: {status_data}")
                    
                    if 'output' not in status_data or 'task_status' not in status_data['output']:
                        error_msg = f"任务状态查询成功，但响应中未包含task_status字段。完整响应: {status_data}"
                        update_task_log(error_msg)
                        return False, error_msg
                    
                    task_status = status_data['output']['task_status']
                    update_task_log(f"任务状态: {task_status}")
                    
                    # 检查任务是否失败
                    if task_status == 'FAILED':
                        error_message = status_data.get('output', {}).get('message', '未知错误')
                        error_code = status_data.get('output', {}).get('code', '未知错误码')
                        error_msg = f"视频生成失败: 错误码 {error_code}, 错误信息: {error_message}"
                        update_task_log(error_msg)
                        return False, error_msg
                    elif task_status == 'SUCCEEDED':
                        if 'video_url' not in status_data['output']:
                            error_msg = f"任务执行成功，但响应中未包含video_url字段。完整响应: {status_data}"
                            update_task_log(error_msg)
                            return False, error_msg
                            
                        video_url = status_data['output']['video_url']
                        update_task_log(f"视频生成完成，URL: {video_url}")
                        break
                    elif task_status == 'CANCELED':
                        error_msg = "视频生成任务已取消"
                        update_task_log(error_msg)
                        return False, error_msg
                else:
                    error_msg = f"查询任务状态失败，状态码: {status_response.status_code}，响应内容: {status_response.text}"
                    update_task_log(error_msg)
                
                attempt += 1
            
            if not video_url:
                error_msg = f"视频生成超时，最终任务状态: {task_status}"
                update_task_log(error_msg)
                return False, error_msg
            
            # 下载视频
            update_task_log("正在下载视频...")
            video_data = requests.get(video_url)
            if video_data.status_code == 200:
                with open(output_path, 'wb') as f:
                    f.write(video_data.content)
                update_task_log(f"视频已保存到: {output_path}")
                return True, output_path
            else:
                error_msg = f"下载视频失败，状态码: {video_data.status_code}"
                update_task_log(error_msg)
                return False, error_msg
        else:
            error_msg = f"提交视频生成任务失败，状态码: {response.status_code}, 错误信息: {response.text}"
            update_task_log(error_msg)
            return False, error_msg
            
    except Exception as e:
        error_msg = f"生成视频时出错: {str(e)}"
        update_task_log(error_msg)
        return False, error_msg


def process_text_to_video(team_a, team_b, match_time, match_name, output_dir, resolution="480*832", task_ref=None):
    """
    处理从文本到视频的完整流程（越南语版本）
    
    Args:
        team_a (str): 球队A名称
        team_b (str): 球队B名称
        match_time (str): 比赛时间
        match_name (str): 赛事名称
        output_dir (str): 输出目录
        resolution (str): 视频分辨率，默认为"480*832"
        task_ref (dict): 任务引用，用于更新状态
        
    Returns:
        tuple: (成功状态, 结果信息)
    """
    # 设置当前任务引用
    if task_ref:
        set_current_task(task_ref)
    
    try:
        update_task_log("开始处理文本到视频任务...")
        
        # 确保输出目录存在
        Path(output_dir).mkdir(parents=True, exist_ok=True)
        
        # 生成文件名
        safe_team_a = re.sub(r'[<>:"/\\|?*]', '_', team_a)
        safe_team_b = re.sub(r'[<>:"/\\|?*]', '_', team_b)
        filename = f"{safe_team_a}_vs_{safe_team_b}_{uuid.uuid4().hex[:8]}.mp4"
        output_path = os.path.join(output_dir, filename)
        
        update_task_log(f"输出路径: {output_path}")
        
        # 1. 生成幽默剧情文本
        success, result = generate_humor_script(team_a, team_b, match_time, match_name)
        if not success:
            return False, result
        
        script_text = result
        
        # 2. 根据文本生成视频
        success, result = generate_video_from_text(script_text, output_path, resolution=resolution)
        if not success:
            return False, result
        
        video_path = result
        
        # 3. 视频转码为更适合录制的格式
        update_task_log("正在进行视频转码...")
        from src.processors.i2v_processor import transcode_video_for_recording
        transcoded_video = Path(output_path).with_suffix('.transcoded.mp4')
        if transcode_video_for_recording(output_path, str(transcoded_video)):
            # 转码成功，替换原文件
            import shutil
            shutil.move(str(transcoded_video), str(output_path))
            update_task_log(f"视频已转码为录制格式: {output_path}")
        else:
            update_task_log("视频转码失败，使用原始格式")
        
        update_task_log("任务处理完成!")
        return True, output_path
        
    except Exception as e:
        error_msg = f"处理过程中出错: {str(e)}"
        update_task_log(error_msg)
        return False, error_msg


def process_excel_to_videos(excel_path, output_dir, task_ref=None):
    """
    处理从Excel到视频的批量生成流程
    
    Args:
        excel_path (str): Excel文件路径
        output_dir (str): 输出目录
        task_ref (dict): 任务引用，用于更新状态
        
    Returns:
        tuple: (成功状态, 结果信息)
    """
    # 设置当前任务引用
    if task_ref:
        set_current_task(task_ref)
    
    try:
        update_task_log("开始处理Excel到视频批量生成任务...")
        update_task_log(f"Excel路径: {excel_path}")
        update_task_log(f"输出目录: {output_dir}")
        
        # 确保输出目录存在
        Path(output_dir).mkdir(parents=True, exist_ok=True)
        
        # 读取Excel文件
        df = pd.read_excel(excel_path)
        
        # 检查必需的列是否存在
        required_columns = ['球队A', '球队B', '比赛时间', '赛事名称']
        missing_columns = [col for col in required_columns if col not in df.columns]
        if missing_columns:
            error_msg = f"Excel文件缺少必需的列: {missing_columns}"
            update_task_log(error_msg)
            return False, error_msg
        
        # 检查是否有视频类型列
        has_video_type = '视频类型' in df.columns
        if has_video_type:
            update_task_log("检测到视频类型列，将根据该列决定视频方向")
        
        update_task_log(f"Excel文件读取成功，共{len(df)}行数据")
        
        generated_videos = []
        failed_videos = []
        
        # 遍历每一行数据生成视频
        for index, row in df.iterrows():
            try:
                team_a = str(row['球队A'])
                team_b = str(row['球队B'])
                match_time = str(row['比赛时间'])
                match_name = str(row['赛事名称'])
                
                # 根据视频类型列决定分辨率
                if has_video_type and str(row['视频类型']).strip().lower() in ['横屏', 'horizontal', 'landscape']:
                    resolution = "832*480"
                    video_type_text = "横屏"
                else:
                    resolution = "480*832"
                    video_type_text = "竖屏"
                
                update_task_log(f"正在处理第{index+1}行数据: {team_a} vs {team_b} ({video_type_text})")
                
                # 生成文件名
                safe_team_a = re.sub(r'[<>:"/\\|?*]', '_', team_a)
                safe_team_b = re.sub(r'[<>:"/\\|?*]', '_', team_b)
                filename = f"{safe_team_a}_vs_{safe_team_b}_{uuid.uuid4().hex[:8]}.mp4"
                output_path = os.path.join(output_dir, filename)
                
                update_task_log(f"输出路径: {output_path}")
                
                # 1. 生成幽默剧情文本
                success, result = generate_humor_script(team_a, team_b, match_time, match_name)
                if not success:
                    failed_videos.append({
                        'index': index+1,
                        'team_a': team_a,
                        'team_b': team_b,
                        'error': result
                    })
                    continue
                
                script_text = result
                
                # 2. 根据文本生成视频
                success, result = generate_video_from_text(script_text, output_path, resolution=resolution)
                if not success:
                    failed_videos.append({
                        'index': index+1,
                        'team_a': team_a,
                        'team_b': team_b,
                        'error': result
                    })
                    continue
                
                video_path = result
                generated_videos.append(video_path)
                
                # 3. 视频转码为更适合录制的格式
                update_task_log("正在进行视频转码...")
                from i2v_processor import transcode_video_for_recording
                transcoded_video = Path(output_path).with_suffix('.transcoded.mp4')
                if transcode_video_for_recording(output_path, str(transcoded_video)):
                    # 转码成功，替换原文件
                    import shutil
                    shutil.move(str(transcoded_video), str(output_path))
                    update_task_log(f"视频已转码为录制格式: {output_path}")
                else:
                    update_task_log("视频转码失败，使用原始格式")
                
                update_task_log(f"第{index+1}行数据处理完成")
                
            except Exception as e:
                error_msg = f"处理第{index+1}行数据时出错: {str(e)}"
                update_task_log(error_msg)
                failed_videos.append({
                    'index': index+1,
                    'team_a': team_a if 'team_a' in locals() else 'Unknown',
                    'team_b': team_b if 'team_b' in locals() else 'Unknown',
                    'error': error_msg
                })
        
        # 生成总结报告
        summary = f"任务处理完成! 成功生成{len(generated_videos)}个视频"
        if failed_videos:
            summary += f"，失败{len(failed_videos)}个"
            update_task_log("失败详情:")
            for failed in failed_videos:
                update_task_log(f"  第{failed['index']}行 ({failed['team_a']} vs {failed['team_b']}): {failed['error']}")
        
        update_task_log(summary)
        return True, {"generated_videos": generated_videos, "failed_videos": failed_videos}
        
    except Exception as e:
        error_msg = f"处理过程中出错: {str(e)}"
        update_task_log(error_msg)
        return False, error_msg
